package com.zoe.tree.service.impl;

import cn.hutool.core.lang.Assert;
import cn.hutool.core.util.CharUtil;
import cn.hutool.core.util.ObjectUtil;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.zoe.tree.entity.DeptAncestors;
import com.zoe.tree.mapper.DeptAncestorsMapper;
import com.zoe.tree.service.DeptAncestorsService;
import org.springframework.stereotype.Service;

import java.util.*;
import java.util.function.Function;
import java.util.stream.Collectors;

/**
 * @author zbg
 * @date 2023/06/19
 * @description $description
 */
@Service
public class DeptAncestorsServiceImpl extends ServiceImpl<DeptAncestorsMapper, DeptAncestors> implements DeptAncestorsService {
    /**
     * 插入一条记录（选择字段，策略插入）
     * @param entity 实体对象
     */
    @Override
    public boolean save(DeptAncestors entity) {

        if (ObjectUtil.isNull(entity.getPid()) || ObjectUtil.equal(entity.getPid(), 0L)) {
            entity.setPid(0L);
            entity.setAncestors("0");
        }
        else {
            DeptAncestors deptAncestors = getById(entity.getPid());
            Assert.notNull(deptAncestors, "上级不存在!");
            entity.setAncestors(deptAncestors.getAncestors() + CharUtil.COMMA + entity.getPid());
        }

        Integer maxSort = baseMapper.getMaxSort(entity.getPid());
        entity.setSort(maxSort + 1);
        return super.save(entity);
    }

    @Override
    public boolean move(DeptAncestors newDeptAncestors) {

        DeptAncestors oldDeptAncestors = baseMapper.selectById(newDeptAncestors.getId());

        Long nextId = newDeptAncestors.getNextId();
        if (ObjectUtil.notEqual(newDeptAncestors.getPid(), oldDeptAncestors.getPid())) { // 如果非同层节点移动

            Integer oldSort = oldDeptAncestors.getSort();
            Long oldPid = oldDeptAncestors.getPid();

            // 如果next节点为空,那么默认放到新pid的最后面的位置,移出位置node的后面元素全部-1
            if (ObjectUtil.isNull(nextId)) {
                Integer maxSort = baseMapper.getMaxSort(newDeptAncestors.getPid());
                newDeptAncestors.setSort(maxSort + 1);
                baseMapper.downSort(oldPid, oldSort);
            }
            else {
                // 非同级，需要切换父节点，原父节点移出位置的后面的元素往前移动一位+1，新父节点移入位置以及的后面的元素往后移动一位
                DeptAncestors nextDept = getById(newDeptAncestors.getNextId());
                Integer newSort = nextDept.getSort();
                newDeptAncestors.setSort(newSort);
                baseMapper.upperSort(newDeptAncestors.getPid(), newSort); // 新父级子节点sort+1
                baseMapper.downSort(oldPid, oldSort); // 旧父级子节点sort-1
            }
        }
        else { // 同级修改
            if (ObjectUtil.isNull(nextId)) {
                Integer maxSort = baseMapper.getMaxSort(newDeptAncestors.getPid());
                newDeptAncestors.setSort(maxSort);
                Integer oldSort = oldDeptAncestors.getSort();
                baseMapper.peerDownSort(newDeptAncestors.getPid(), maxSort, oldSort);
            }
            else {
                DeptAncestors nextDept = getById(newDeptAncestors.getNextId());
                Integer newSort = nextDept.getSort();
                Integer oldSort = oldDeptAncestors.getSort();
                if (oldSort > newSort) { // 如果原来的sort比next的sort大;说明我现在是要放在next节点的前面
                    newDeptAncestors.setSort(newSort);
                    baseMapper.peerUpperSort(newDeptAncestors.getPid(), newSort, oldSort);
                }
                else {
                    int newSortDecrement = newSort - 1;
                    newDeptAncestors.setSort(newSortDecrement);
                    baseMapper.peerDownSort(newDeptAncestors.getPid(), newSortDecrement, oldSort);
                }
            }
        }

        return updateById(newDeptAncestors);
    }

    /**
     * 批量删除(jdbc批量提交)
     * @param list 主键ID或实体列表(主键ID类型必须与实体类型字段保持一致)
     * @return 删除结果
     * @since 3.5.0
     */
    @Override
    public boolean removeBatchByIds(Collection<?> list) {
        for (Object o : list) {
            DeptAncestors deptAncestors = getById((Long) o);
            baseMapper.downSort(deptAncestors.getPid(), deptAncestors.getSort());
        }
        return super.removeBatchByIds(list);
    }

    @Override
    public Set<DeptAncestors> tree() {
        Set<DeptAncestors> resList = new TreeSet<>();
        List<DeptAncestors> list = list();

        Map<Long, DeptAncestors> map = list.stream()
                                           .collect(Collectors.toMap(DeptAncestors::getId, Function.identity(), (k1, k2) -> k1));

        for (DeptAncestors target : list) {
            Long pid = target.getPid();
            DeptAncestors parentDept = map.get(pid);
            if (parentDept == null) {
                resList.add(target);
                continue;
            }
            parentDept.addChildren(target);
        }
        return resList;
    }
}
